#include "StringList.h"
#include <string.h>


CStringList::CStringList() : _LastSlot(0)
{
	memset(_Slots, 0, MAPSLOTSCOUNT * sizeof(void*));
	_LastSlot = _FirstSlot = new ListSlot("", 0, 0, &_LastSlot, *this);
	_Count = 1;
}

size_t CStringList::getIndexByString(const char* String)
{
	size_t SlotIndex = getSlotIndex(String);
	ListSlot* Slot = _Slots[SlotIndex];
	while (Slot) {
		if (strcmp(Slot->_String, String) == 0) {
			return Slot->_Index;
		}
		Slot = Slot->_Next;
	}
	_Slots[SlotIndex] = new ListSlot(String, _Count, _Slots[SlotIndex], &_LastSlot, *this);
	_Count++;
	return _LastSlot->_Index;
}

CStringList::~CStringList()
{
	if (_FirstSlot){
		delete _FirstSlot;
	}
}

const char* CStringList::getStringByIndex(size_t Index)
{
	ListSlot* Slot = _FirstSlot;
	while (Slot && Slot->_Index < Index){
		Slot = Slot->_NextByIndex;
	}
	if (Slot){
		return Slot->_String;
	}
	return 0;
}

int CStringList::getHash(const char* Key)
{
	int l = strlen(Key);
	unsigned int h = (unsigned int)l; /* seed */
	int step = (l >> 5) | 1;  /* if string is too long, don't hash all its chars */
	for (; l >= step; l -= step, Key++)
		h = h ^ ((h << 5) + (h >> 2) + (unsigned int)*Key);
	return h;
}

CStringList::ListSlot::ListSlot(const char* String, size_t Index, ListSlot* NextSlot, ListSlot** LastSlot, CStringList& Base) :_Index(Index), _Next(NextSlot), _NextByIndex(0)
{
	_Strlen = strlen(String);
	_String = new char[_Strlen + 1];
	_String[_Strlen] = 0;
	strcpy(_String, String);
	if (*LastSlot){
		(*LastSlot)->_NextByIndex = this;
	}
	*LastSlot = this;
	Base._CharsCount += _Strlen;
}

CStringList::ListSlot::~ListSlot()
{
	if (_NextByIndex){
		delete _NextByIndex;
	}
	delete[] _String;
}